#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import functools
import threading
import time
from logging import Logger

from common.util.common_utils import proactively_report_progress

monitor_progress_thread = None


class MonitorProgressThread(threading.Thread):
    def __init__(self, pid, sub_job_detail, logger_inst):
        super(MonitorProgressThread, self).__init__(name=f"monitor_process_{pid}")
        self.pid = pid
        self.sub_job_detail = sub_job_detail
        self.logger_inst = logger_inst
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

    def run(self) -> None:
        while True:
            if self.stopped():
                return
            proactively_report_progress(self.pid, self.sub_job_detail, self.logger_inst)
            # 备份过程中上报进度间隔时间，必须小于5min（300s）
            time.sleep(30)


def monitor_report_progress_decorator(pid, sub_job_detail, logger_inst: Logger):
    """监测任务并上报进度装饰器"""

    def decorator(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            global monitor_progress_thread
            try:
                monitor_progress_thread = MonitorProgressThread(pid, sub_job_detail, logger_inst)
                monitor_progress_thread.setDaemon(True)
                monitor_progress_thread.start()
            except threading.ThreadError:
                logger_inst.exception("Start monitor task thread failed.")
            task_result = func(*args, **kwargs)
            monitor_progress_thread.stop()
            # 等待监测进度线程结束
            monitor_progress_thread.join()
            return task_result

        return inner

    return decorator
